﻿using System;
using System.Collections.Generic;
using System.Text;
using ESPlus.Application.CustomizeInfo.Server;
using ESPlus.Application.Basic.Server;
using ESPlus.Application.CustomizeInfo;
using GG.Core;
using ESFramework.Server.UserManagement;
using ESPlus.Rapid;
using ESPlus.Serialization;

namespace GG.Server
{
    /// <summary>
    /// 自定义信息处理器
    /// </summary>
    internal class CustomizeHandler : IIntegratedCustomizeHandler 
    {
        private IGGPersister ggPersister;
        private IRapidServerEngine rapidServerEngine;
        private OfflineFileController offlineFileController;
        private OfflineMessageController offlineMessageController;
        public void Initialize(IGGPersister db, IRapidServerEngine engine, OfflineMessageController msgCtr, OfflineFileController fileCtr)
        {
            this.ggPersister = db;
            this.rapidServerEngine = engine;
            this.offlineMessageController = msgCtr;
            this.offlineFileController = fileCtr;
        }

        /// <summary>
        /// 处理来自客户端的消息。
        /// </summary> 
        public void HandleInformation(string sourceUserID, int informationType, byte[] info)
        {
            if (informationType == InformationTypes.GetOfflineMessage)
            {
                this.offlineMessageController.SendOfflineMessage(sourceUserID);
                return;
            }

            if (informationType == InformationTypes.GetOfflineFile)
            {
                this.offlineFileController.SendOfflineFile(sourceUserID);
                return;
            }

            if (informationType == InformationTypes.QuitGroup)
            {
                string groupID = System.Text.Encoding.UTF8.GetString(info) ;
                this.ggPersister.QuitGroup(sourceUserID, groupID);
                //通知其它组成员
                this.rapidServerEngine.GroupController.Broadcast(groupID, BroadcastTypes.SomeoneQuitGroup, System.Text.Encoding.UTF8.GetBytes(sourceUserID), ESFramework.ActionTypeOnChannelIsBusy.Continue);
              
                return;
            }

            if (informationType == InformationTypes.RemoveFriend)
            {
                string friendID = System.Text.Encoding.UTF8.GetString(info);
                this.ggPersister.RemoveFriend(sourceUserID, friendID);
                //通知好友
                this.rapidServerEngine.CustomizeController.Send(friendID, InformationTypes.FriendRemovedNotify, System.Text.Encoding.UTF8.GetBytes(sourceUserID));
                return;
            }
        }

        /// <summary>
        /// 处理来自客户端的同步调用请求。
        /// </summary>       
        public byte[] HandleQuery(string sourceUserID, int informationType, byte[] info)
        {
            if (informationType == InformationTypes.GetFriends)
            {
                List<string> friendIDs = this.ggPersister.GetFriends(sourceUserID);
                List<User> friends = new List<User>();
                foreach (string friendID in friendIDs)
                {
                    User friend = this.ggPersister.GetUser(friendID);
                    friend.Online = this.rapidServerEngine.UserManager.IsUserOnLine(friendID);
                    friends.Add(friend);
                }

                return GGHelper.SerializeObject(friends);
            }

            if (informationType == InformationTypes.GetUserInfo)
            {
                User user = this.ggPersister.GetUser(System.Text.Encoding.UTF8.GetString(info));
                user.Online = this.rapidServerEngine.UserManager.IsUserOnLine(user.ID);
                return GGHelper.SerializeObject(user);
            }

            if (informationType == InformationTypes.AddFriend)
            {
                string friendID = System.Text.Encoding.UTF8.GetString(info);
                bool isExist = this.ggPersister.IsUserExist(friendID);
                if (!isExist)
                {
                    return BitConverter.GetBytes((int)AddFriendResult.FriendNotExist);
                }
                this.ggPersister.AddFriend(sourceUserID, friendID);
                //通知对方
                this.rapidServerEngine.CustomizeController.Send(friendID, InformationTypes.FriendAddedNotify, System.Text.Encoding.UTF8.GetBytes(sourceUserID), true, ESFramework.ActionTypeOnChannelIsBusy.Continue);
                return BitConverter.GetBytes((int)AddFriendResult.Succeed);
            }

            if (informationType == InformationTypes.GetMyGroups)
            {
                List<Group> myGroups = this.ggPersister.GetMyGroups(sourceUserID);
                return GGHelper.SerializeObject(myGroups);
            }

            if (informationType == InformationTypes.JoinGroup)
            {
                string groupID = System.Text.Encoding.UTF8.GetString(info);
                JoinGroupResult res = this.ggPersister.JoinGroup(sourceUserID, groupID);
                if (res == JoinGroupResult.Succeed)
                {
                    //通知其它组成员
                    this.rapidServerEngine.GroupController.Broadcast(groupID, BroadcastTypes.SomeoneJoinGroup, System.Text.Encoding.UTF8.GetBytes(sourceUserID), ESFramework.ActionTypeOnChannelIsBusy.Continue);
                }
                return BitConverter.GetBytes((int)res);
            }

            if (informationType == InformationTypes.CreateGroup)
            {
                CreateGroupContract contract = CompactPropertySerializer.Default.Deserialize<CreateGroupContract>(info, 0);
                CreateGroupResult res = this.ggPersister.CreateGroup(sourceUserID, contract.ID, contract.Name);               
                return BitConverter.GetBytes((int)res);
            }

            if (informationType == InformationTypes.GetGroup)
            {
                string groupID = System.Text.Encoding.UTF8.GetString(info);
                Group group = this.ggPersister.GetGroup(groupID);
                return GGHelper.SerializeObject(group);
            }

            if (informationType == InformationTypes.ChangePassword)
            {
                ChangePasswordContract contract = CompactPropertySerializer.Default.Deserialize<ChangePasswordContract>(info, 0);
                ChangePasswordResult res = this.ggPersister.ChangePassword(sourceUserID, contract.OldPasswordMD5, contract.NewPasswordMD5);
                return BitConverter.GetBytes((int)res);
            }
           
            return null;
        }

        public bool CanHandle(int informationType)
        {
            return InformationTypes.ContainsInformationType(informationType);
        }
    }
}
